package tech.xs.sys.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import tech.xs.common.auth.domain.enums.AuthPathWhiteTypeEnum;
import tech.xs.common.framework.domain.annotations.AuthApi;
import tech.xs.common.framework.domain.entity.BaseEntity;
import tech.xs.common.framework.domain.enums.DataSourceTypeEnum;
import tech.xs.common.framework.domain.model.ApiResult;
import tech.xs.common.framework.domain.model.PageResult;
import tech.xs.common.framework.util.DictUtil;
import tech.xs.common.sys.domain.constant.PermissionConstant;
import tech.xs.sys.domain.bo.dict.ManualEditDictBo;
import tech.xs.sys.domain.bo.dict.PageDictBo;
import tech.xs.sys.domain.entity.SysDict;
import tech.xs.sys.domain.entity.SysDictData;
import tech.xs.sys.service.SysDictDataService;
import tech.xs.sys.service.SysDictService;

import javax.annotation.Resource;
import java.util.List;

/**
 * 字典管理
 *
 * @author 沈家文
 * @since 2023/5/10 13:24
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/dict")
public class SysDictController {

    @Resource
    private SysDictService sysDictService;
    @Resource
    private SysDictDataService sysDictDataService;

    /**
     * 通过字典code从缓存中查询字典数据
     * <p>
     *
     * @param dictCode 字典编码
     * @return 1.全局通用返回结构<br>2.返回封装后的字典,以及字典数据
     * @author 沈家文
     * @since 2023/5/10 14:09
     */
    @GetMapping("/get")
    @AuthApi(type = AuthPathWhiteTypeEnum.ALL)
    public String getDict(@RequestParam String dictCode) {
        return sysDictService.getDictCache(dictCode);
    }

    /**
     * 分页查询字典
     *
     * @param bo 请求参数
     * @return 响应结果
     * @author 沈家文
     * @since 2023/5/15 17:34
     */
    @GetMapping("/list/page")
    @AuthApi(permissions = PermissionConstant.DICT_MGR)
    public PageResult<SysDict> page(@ModelAttribute PageDictBo bo) {
        return PageResult.success(sysDictService.page(bo.page(), bo.query()));
    }

    /**
     * 新增或更新字典
     *
     * @param bo 请求数据
     * @return 响应数据
     * @author 沈家文
     * @since 2023/5/15 17:34
     */
    @PostMapping("/saveOrUpdate/manual")
    @AuthApi(permissions = PermissionConstant.DICT_MGR)
    public ApiResult<SysDict> manualEdit(@Validated @RequestBody ManualEditDictBo bo) {
        bo.checkParameter();

        long existCount = sysDictService.count(Wrappers.<SysDict>lambdaQuery()
                .eq(SysDict::getCode, bo.getCode())
                .ne(bo.getId() != null, BaseEntity::getId, bo.getId()));
        if (existCount > 0) {
            return ApiResult.error("字典编码已经存在");
        }

        SysDict saveData = new SysDict();
        BeanUtil.copyProperties(bo, saveData);
        if (bo.getId() != null) {
            SysDict dbData = sysDictService.getOne(Wrappers.<SysDict>lambdaQuery().eq(BaseEntity::getId, bo.getId()));
            if (dbData == null) {
                return ApiResult.error("根据id在系统中未查询到数据");
            }
            if (DataSourceTypeEnum.SystemGeneration.equals(dbData.getSource())) {
                return ApiResult.error("系统生成字典禁止修改");
            }
            List<SysDictData> dictDataList = sysDictDataService.list(Wrappers.<SysDictData>lambdaQuery().eq(SysDictData::getDictId, bo.getId()));
            for (SysDictData dictData : dictDataList) {
                try {
                    DictUtil.getCodeValue(saveData.getValueType(), dictData.getCode());
                } catch (Exception e) {
                    log.error("code与字典数据类型不匹配", e);
                    return ApiResult.error("code与字典数据类型不匹配 valueType:" + saveData.getValueType() + " code:" + dictData.getCode());
                }
            }
            if (!bo.getCode().equals(dbData.getCode())) {
                sysDictService.deleteDictCache(dbData.getCode());
            }
        }

        saveData.setSource(DataSourceTypeEnum.Manual);
        log.info("手动更新或保存字典:" + saveData);
        sysDictService.saveOrUpdate(saveData);
        sysDictService.reloadDictCache(saveData.getCode());
        return ApiResult.success(saveData);
    }

    /**
     * 根据字段编码删除字典
     * <p>
     * 1.删除字典关联数据
     * 2.删除字典缓存
     *
     * @param dictCode 字典编码
     * @return 响应数据
     * @author 沈家文
     * @since 2023/5/11 17:23
     */
    @DeleteMapping("/delete/code")
    @AuthApi(permissions = PermissionConstant.DICT_MGR)
    public ApiResult<String> deleteByCode(@RequestParam String dictCode) {
        if (StrUtil.isBlank(dictCode)) {
            return ApiResult.error("dictCode不能为空");
        }
        long count = sysDictService.count(Wrappers.<SysDict>lambdaQuery().eq(SysDict::getCode, dictCode));
        if (count <= 0) {
            return ApiResult.error("字典不存在或已删除:" + dictCode);
        }
        log.info("删除字典:" + dictCode);
        sysDictService.deleteDictByCode(dictCode);
        return ApiResult.success(dictCode);
    }

}
